﻿namespace JoinBox.Forms;

using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

#pragma warning disable CA1806 // 不要忽略方法结果
public class AcadProductKey
{
    /// <summary>
    /// 注册表位置
    /// </summary>
    public RegistryKey? ProductKey;
    /// <summary>
    /// cad安装路径
    /// </summary>
    public string? Location;
    /// <summary>
    /// cad名称
    /// </summary>
    public string? ProductName;
    /// <summary>
    /// cad版本号 17.1之类的
    /// </summary>
    public string? Version;
    public double VerNumber
    {
        get
        {
            if (Version is not null)
            {
                var strVer = Version.Split('.');
                double.TryParse(strVer[0] + "." + strVer[1], out double ver);
                return ver;
            }
            return 0.0;
        }
    }
    public Guid Guid;
}

internal class AcadRegedit
{
    /// <summary>
    /// 注册表路径,已经最小到最大排序
    /// </summary>
    internal static List<AcadProductKey>? AcadProductKeys { get; }

    static AcadRegedit()
    {
        AcadProductKeys = GetAcadProductKeys();
        GetGuidKeys(AcadProductKeys);
    }

    /// <summary>
    /// 获取Guid
    /// </summary>
    /// <param name="apk"></param>
    static void GetGuidKeys(List<AcadProductKey>? apk)
    {
        if (apk is null)
            throw new ArgumentException(null, nameof(apk));

        const string appReg = "AutoCAD.Application";
        const string appRegDot = appReg + ".";

        // var fmts = new string[] { @"Software\Classes", @"Software\Wow6432Node\Classes" };
        var fmts = new string[] { @"Software\Classes" };// 只需要在32位上面找

        foreach (var fmt in fmts)
        {
            var classes = Registry.LocalMachine.OpenSubKey(fmt);
            if (classes is null)
                continue;

            foreach (var verReg in classes.GetSubKeyNames())
            {
                try
                {
                    if (!verReg.Contains(appReg))
                        continue;
                    var app = classes.OpenSubKey(verReg);
                    if (app is null)
                        continue;
                    var clsid = app.OpenSubKey("CLSID");
                    if (clsid is null)
                        continue;

                    var verStr = verReg.Replace(appRegDot, string.Empty);
                    double.TryParse(verStr, out double verNumber);
                    foreach (var item in apk)
                    {
                        if (item.VerNumber == verNumber)
                        {
                            var guidStr = clsid.GetValue(null)?.ToString();
                            if (guidStr is not null)
                                item.Guid = new Guid(guidStr);
                            break;
                        }
                    }
                }
                catch
                { }
            }
        }
    }

    /// <summary>
    /// 获取注册表版本信息和安装路径
    /// </summary>
    /// <returns></returns>
    static List<AcadProductKey>? GetAcadProductKeys()
    {
        var adsk = Registry.CurrentUser.OpenSubKey(@"Software\Autodesk\AutoCAD");
        if (adsk is null)
            return null;

        var apk = new List<AcadProductKey>();
        foreach (var subName in adsk.GetSubKeyNames())
        {
            try
            {
                var emnuAcad = adsk.OpenSubKey(subName);
                var curver = emnuAcad?.GetValue("CurVer");
                if (curver is null)
                    continue;
                var app = curver.ToString();
                var fmt = @"Software\Autodesk\AutoCAD\{0}\{1}";
                emnuAcad = Registry.LocalMachine.OpenSubKey(string.Format(fmt, subName, app));
                if (emnuAcad is null)
                {
                    fmt = @"Software\Wow6432Node\Autodesk\AutoCAD\{0}\{1}";
                    emnuAcad = Registry.LocalMachine.OpenSubKey(string.Format(fmt, subName, app));
                }

                if (emnuAcad is not null)
                {
                    var acadLocation = emnuAcad.GetValue("AcadLocation");
                    if (acadLocation is null)
                        continue;
                    var location = acadLocation.ToString();
                    if (location is null)
                        continue;
                    if (File.Exists(location + "\\acad.exe"))
                    {
                        var produ = emnuAcad.GetValue("ProductName");
                        var release = emnuAcad.GetValue("Release");
                        if (release is null)
                            continue;
                        var strVer = release.ToString()?.Split('.');
                        var pro = new AcadProductKey()
                        {
                            ProductKey = emnuAcad,
                            Location = location,
                            ProductName = produ?.ToString(),
                        };
                        if (strVer is not null && strVer.Length > 2)
                            pro.Version = strVer[0] + "." + strVer[1];
                        apk.Add(pro);
                    }
                }
            }
            catch { }
        }
        apk = apk.OrderBy(cad => cad.Version).ToList();
        return apk;
    }
}

#pragma warning restore CA1806 // 不要忽略方法结果
